package com.MyDemo.demo;

import com.MyDemo.demo.context.OrderContext;
import com.MyDemo.demo.domain.WtTest;
import com.MyDemo.demo.enums.OrderEventsEnum;
import com.MyDemo.demo.enums.OrderStatusEnum;
import com.MyDemo.demo.mapper.WtTestMapper;
import com.MyDemo.demo.strategy.AcceptRule;
import com.MyDemo.demo.strategy.DistanceRule;
import com.MyDemo.demo.strategy.IProcessRule;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.statemachine.StateMachine;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import javax.crypto.SecretKey;

@SpringBootTest
public class MyTestClass {
    Logger logger = LoggerFactory.getLogger("MyTestClass");

    @Resource
    private StateMachine<OrderStatusEnum, OrderEventsEnum> orderStateMachine;

    @Autowired
    private RedissonClient redissonClient;

    @Resource
    private WtTestMapper wtTestMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    public void test1() {
        WtTest wtTest = new WtTest();
        wtTest.setTestInt(2);
        wtTest.setTestString("hello");
        wtTestMapper.insert(wtTest);
    }

    @Test
    public void test2() {
        LambdaQueryChainWrapper<WtTest> wrapper = new LambdaQueryChainWrapper<>(WtTest.class);
        WtTest one = wrapper.eq(WtTest::getTestInt, 1).one();
        logger.info(one.toString());
    }

    /**
     * redisson锁测试
     */
    @Test
    public void func() {
        RLock lock = redissonClient.getLock("myLock");
        try {
            // 尝试获取锁，最多等待3秒，持锁时间为5秒
            boolean isLockAcquired = lock.tryLock(3, 100, TimeUnit.SECONDS);
            if (isLockAcquired) {
                try {
                    logger.info("获得锁");
                    Thread.sleep(1000000);
                } finally {
                    // 释放锁
                    lock.unlock();
                }
            } else {
                // 获取锁失败，处理相应逻辑
                logger.warn("没有获得锁");
            }
        } catch (InterruptedException e) {
            // 处理中断异常
        }
    }

    /**
     * redisson锁测试
     */
    @Test
    public void func2() {
        RLock lock = redissonClient.getLock("myLock");
        try {
            // 尝试获取锁，最多等待3秒，持锁时间为5秒
            boolean isLockAcquired = lock.tryLock(15, 25, TimeUnit.SECONDS);
            if (isLockAcquired) {
                try {
                    logger.info("获得锁");
                    // Thread.sleep(1000000);
                } finally {
                    // 释放锁
                    // lock.unlock();
                }
            } else {
                // 获取锁失败，处理相应逻辑
                logger.warn("没有获得锁");
            }
        } catch (InterruptedException e) {
            // 处理中断异常
        }
    }

    /**
     * 测试向redis中写入实体转化成json后的String数据
     */
    @Test
    public void toStringToRedis() {
        WtTest wtTest = new WtTest();
        wtTest.setTestString("测试");
        wtTest.setTestInt(123);

        ObjectMapper mapper = new ObjectMapper();
        try {
            String s = mapper.writeValueAsString(wtTest);
            redisTemplate.opsForValue().set("wt:key", s, 15, TimeUnit.SECONDS);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 测试从redis中读回json数据并转化为实体
     */
    @Test
    public void func3() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();

        String s1 = redisTemplate.opsForValue().get("wt:key");
        if (Objects.nonNull(s1)) {
            WtTest wtTest = mapper.readValue(s1, WtTest.class);
            logger.info("String:{}", wtTest.getTestString());
            logger.info("Integer:{}", wtTest.getTestInt());
        }
    }

    @Test
    public void func5() {
        redisTemplate.opsForHash().put("A:B", "key1", "1");
        redisTemplate.opsForHash().put("A:B", "key2", "2");
        redisTemplate.opsForHash().put("A:B", "key4", "4");
    }

    /**
     * cacheHelper原理测试
     */
    @Test
    public void func7() {
        ArrayList<Object> strings = new ArrayList<>();
        strings.add("key1");
        strings.add("key2");
        strings.add("key3");
        strings.add("key4");
        List<Object> objects = redisTemplate.opsForHash().multiGet("A:B", strings);
        AtomicInteger a = new AtomicInteger(-1);
        objects.stream().forEach(x -> System.out.println(x));
        objects.stream().forEach(x -> {
            a.incrementAndGet();
            if (Objects.isNull(x)) {
                logger.warn("到数据库中查询{}并上传至redis中, 再加入到list对应下标的元素中", a.intValue());
            } else
                logger.info("打印当前的下标值为{}", a.intValue());
        });
    }

    @Test
    public void func4() {
        System.err.println(func6());
    }

    public int func6() {
        try {
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            return 3;
        }
    }

    /**
     * 状态机测试
     */
    @Test
    public void func8() {
        orderStateMachine.start();
        orderStateMachine.sendEvent(OrderEventsEnum.ORDER);
    }

    /**
     * 策略模式测试
     */
    @Test
    public void func9() {
        OrderContext orderContext = new OrderContext(OrderEventsEnum.ORDER);
        orderContext.executeStrategy(OrderEventsEnum.ORDER);

        orderContext.setStrategy(OrderEventsEnum.RECEIVE);
        orderContext.executeStrategy(OrderEventsEnum.RECEIVE);
    }

    @Test
    public void func10() {
        String a = "事件枚举的类型是:";
        String format = String.format("%s%s", a, OrderEventsEnum.ORDER);
        logger.info(format);
    }

    @Test
    public void func11() {
        for (int i = 0; i < 10; i++) {
        }
    }

    /**
     * 责任链模式测试
     */
    @Test
    public void func12() {
        IProcessRule a = new AcceptRule();
        DistanceRule b = new DistanceRule(a);
        b.filter(null);
    }

    /**
     * 随便测试
     */
    @Test
    public void testa() {
        logger.error("===========================================================");
    }

    @Test
    public void testb() {
        redisTemplate.opsForSet().add("set:key", "value1", "value2", "value3");
    }

    /**
     * 测试redis中的set集合
     */
    @Test
    public void testc() {
        Set<String> members = redisTemplate.opsForSet().members("set:key");
        int[] i = { 0 };

        if (Objects.nonNull(members)) {
            List<String> list1 = members.stream().map(x -> {
                i[0]++;
                String format = String.format("第%d个是%s ", i[0], x);
                return format;
            }).collect(Collectors.toList());

            list1.forEach(x -> logger.info(x));
        }
    }

    @Test
    public void func14() {
        SecretKey key = Keys.hmacShaKeyFor("itwt12341234asdfasdf12341234123412341234".getBytes(StandardCharsets.UTF_8));
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("username", "wt");
        hashMap.put("age", "25");
        String jws = Jwts.builder().claims(hashMap).signWith(key).compact();
        logger.info(jws);
    }

    @Test
    public void func13() {
        SecretKey key = Keys.hmacShaKeyFor("itwt12341234asdfasdf12341234123412341234".getBytes(StandardCharsets.UTF_8));
        String jws = "eyJhbGciOiJIUzI1NiJ9.eyJhZ2UiOiIyNSIsInVzZXJuYW1lIjoid3QifQ.K8cZ2fF-EKIwpnFYNrTWhhtY2rpfE6diNpnqvQxmhHg";
        /*
         * String subject =
         * Jwts.parser().verifyWith(key).build().parseSignedClaims(jws).getPayload().
         * getSubject();
         */
        Claims payload = Jwts.parser().verifyWith(key).build().parseSignedClaims(jws).getPayload();
        Object object = payload.get("username");
        logger.info("=============================================");
        logger.info("result is :" + String.valueOf(object));
        logger.info("=============================================");
    }

}
